﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using UnityEditor;
using UnityEngine;
using Random = System.Random;

namespace XUGarbage
{
    namespace Editor
    {
        /// <summary>
        /// 垃圾资源生成器
        /// 生成路径：Application.streamingAssetsPath + "/garbage/"
        /// </summary>
        public class XUGarbageAssetGenerator
        {
            public static string garbagePath = Application.streamingAssetsPath + "/garbage/";
            private static List<string> wordLib = new List<string>();

            //生成资源
            [MenuItem("XUPK/XUGarbage/Garbage Asset", false, 1)]
            public static void GenerateGarbageAssetMenu()
            {
                GenerateGarbageAsset();
            }

            public static void GenerateGarbageAsset(int countMin = 1000, int countMax = 1500)
            {
                //模板文件
                string tmpAsset = Application.dataPath + "/tmpAsset.asset";
                File.WriteAllText(tmpAsset, "");

                //检查文件夹
                if (Directory.Exists(garbagePath))
                {
                    Directory.Delete(garbagePath, true);
                }
                Directory.CreateDirectory(garbagePath);

                //循环生成
                int assetCount = UnityEngine.Random.Range(countMin, countMax);
                int encryptKey = UnityEngine.Random.Range(10000000, 99999999);
                for (int i = 0; i < assetCount; i++)
                {
                    EditorUtility.DisplayProgressBar("生成垃圾资源", "生成中..", i * 1f / assetCount * 1f);

                    byte[] randomBytes = EncryptEx(Encoding.Default.GetBytes(GetRandomString(UnityEngine.Random.Range(1000, 150000), true, true, true, true, "")), encryptKey.ToString());
                    File.WriteAllBytes(tmpAsset, randomBytes);

                    string savePath = garbagePath + "/" + RandomName() + ".asset";
                    File.Copy(tmpAsset, savePath, true);
                }

                File.Delete(tmpAsset);

                EditorUtility.ClearProgressBar();
                AssetDatabase.Refresh();

                Debug.Log("generate Garbage asset finish.");
            }

            ///<summary>
            ///生成随机字符串 
            ///</summary>
            ///<param name="length">目标字符串的长度</param>
            ///<param name="useNum">是否包含数字，1=包含，默认为包含</param>
            ///<param name="useLow">是否包含小写字母，1=包含，默认为包含</param>
            ///<param name="useUpp">是否包含大写字母，1=包含，默认为包含</param>
            ///<param name="useSpe">是否包含特殊字符，1=包含，默认为不包含</param>
            ///<param name="custom">要包含的自定义字符，直接输入要包含的字符列表</param>
            ///<returns>指定长度的随机字符串</returns>
            private static string GetRandomString(int length, bool useNum, bool useLow, bool useUpp, bool useSpe, string custom)
            {
                byte[] b = new byte[4];
                new System.Security.Cryptography.RNGCryptoServiceProvider().GetBytes(b);
                Random r = new Random(BitConverter.ToInt32(b, 0));
                StringBuilder s = new StringBuilder();
                string str = custom;
                if (useNum == true)
                {
                    str += "0123456789";
                }
                if (useLow == true)
                {
                    str += "abcdefghijklmnopqrstuvwxyz";
                }
                if (useUpp == true)
                {
                    str += "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
                }
                if (useSpe == true)
                {
                    str += "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
                }
                for (int i = 0; i < length; i++)
                {
                    s.Append(str.Substring(r.Next(0, str.Length - 1), 1));
                }
                return s.ToString();
            }

            /// <summary>
            /// 加密
            /// </summary>
            /// <param name="data">字节流</param>
            /// <param name="pass">秘钥</param>
            /// <returns></returns>
            private static Byte[] EncryptEx(Byte[] data, String pass)
            {
                if (data == null || pass == null)
                    return null;
                Byte[] output = new Byte[data.Length];
                Int64 i = 0;
                Int64 j = 0;
                Byte[] mBox = GetKey(Encoding.Default.GetBytes(pass), 256);
                // 加密
                for (Int64 offset = 0; offset < data.Length; offset++)
                {
                    i = (i + 1) % mBox.Length;
                    j = (j + mBox[i]) % mBox.Length;
                    Byte temp = mBox[i];
                    mBox[i] = mBox[j];
                    mBox[j] = temp;
                    Byte a = data[offset];
                    //Byte b = mBox[(mBox[i] + mBox[j] % mBox.Length) % mBox.Length];
                    // mBox[j] 一定比 mBox.Length 小，不需要在取模
                    Byte b = mBox[(mBox[i] + mBox[j]) % mBox.Length];
                    output[offset] = (Byte)((Int32)a ^ (Int32)b);
                }
                return output;
            }

            /// <summary>
            /// 打乱密码
            /// </summary>
            /// <param name="pass">密码</param>
            /// <param name="kLen">密码箱长度</param>
            /// <returns>打乱后的密码</returns>
            private static Byte[] GetKey(Byte[] pass, Int32 kLen)
            {
                Byte[] mBox = new Byte[kLen];
                for (Int64 i = 0; i < kLen; i++)
                {
                    mBox[i] = (Byte)i;
                }
                Int64 j = 0;
                for (Int64 i = 0; i < kLen; i++)
                {
                    j = (j + mBox[i] + pass[i % pass.Length]) % kLen;
                    Byte temp = mBox[i];
                    mBox[i] = mBox[j];
                    mBox[j] = temp;
                }
                return mBox;
            }

            private static string RandomName()
            {
                if (wordLib.Count == 0)
                {
                    wordLib.AddRange("layout,window,adapter,dataSource,collectionView,position,selector,stubEnabled,object,message,logFileManager,handleKeyboardEvents,handleEvents,gameSystemResponderClientProtocol,gameCoreOwner,gameCore,screenSize,aspectSize,loadedRom,surfaceID,isEmulationPaused,hasRun,action,target,gameCoreHelper,defaultMigrationController,versionComparator,toolTipStyle,sharedToolTipManager,currentStyle,stateMask,thread,target,angle,selectedThemeTextAttributes,selectedThemeTextAttributes,sharedTheme,headerState,objectsByType,isEditing,selectionColor,clickable,backgroundColor,task,responderClass,bundleIcon,systemIcon,systemIdentifier,coverAspectRatio,supportsDiscs,systemName,controller,levelThemeImage,dropBorderWidth,dropBackgroundColor,dropBorderColor,isDrawingAboveDropHighlight,dropCornerRadius,autosaveName,name,editingItem,groups,database,view,collections,container,groups,gameScannerViewController,collections,systems,scrollersFlashed,isEditing,badge,isGroup,image,selectionColor,badgeAttributes,groupAttributes,highlightGradient,itemAttributes,themeKey,maxHint,minHint,layer,containingWindow,renderer,runningTime,lastState,isEditing,selectedThemeTextAttributes,gameScannerAllowView,installCoreTableView,name,replaceView,gameScannerVolumeSelectionView,mountedVolumesTableView,allowScanForGames,downloadRequested,core,lastStepView,URL,coreSelectionView,welcomeView,OEFSMEventNumber,selected,defaultCore,themeKey,selectedThemeTextAttributes,trackImage,knobImage,stateMask,isVertical,candyOffset,animating,paused,viewSize,icon,localizedTitle,title,delegate,database,totalNumberOfItems,context,numberOfProcessedItems,status,operationQueue,database,spotlightSearchResults,totalNumberOfItems,context,numberOfProcessedItems,status,pathField,librariesView,filterSelection,tableView,coresTableView,keyDescriptions,mainWindow,tableView,currentSystemController,currentPlayerBindings,playerPopupButton,consolesPopupButton,inputPopupButton,controllerContainerView,selectedKey,selectedPlayer,currentSystemBindings,gradientOverlay,controllerView,controlsSetupView,controlsContainer,currentPlayerBindings,currentSystemBindings,windowFullScreen,items,fileSystemWatcher,screenshotView,screenshot,bundle,infoDictionary,allPluginNames,name,details,displayName,version,pluginType,pluginExtension,allPlugins,pluginClasses,path,availablePreferenceViewControllerKeys,pluginFolder,controller,isPluginClass,lutTextures,NTSCFilter,numberOfPasses,shaders,manager,indicator,selectedSaveStates,selectedScreenshots,saveStateMode,bottomBorderColor,topHighlightColor,titlebarBackgroundView,backgroundGradient,state,searchKeys,currentSearchTerm,saveStateMode,screenshot,shouldShowBlankSlate,items,searchPredicate,groupRanges,libraryController,currentContentController,placeholderView,allowWindowResizing,defaultContentController,mainWindowRunsGame,splitterPosition,libraryController,selectedGames,sidebarVisualEffectView,libraryController,collectionController,sidebarController,collectionViewContainer,gameScannerController,autoImportWatcher,databaseURL,saveStateWatcher,managedObjectModel,previousWidth,saveStatesViewController,libraryGamesViewController,homebrewViewController,screenshotsViewController,currentSubviewController,selectedCategory,currentSubviewController,toolbar,database,delegate,autoImportFolderURL,screenshotFolderURL,persistentStoreCoordinator,lastPlayedRoms,writerContext,unsortedRomsFolderURL,stateFolderURL,coverFolderURL,importer,databaseFolderURL,romsFolderURL,lastPlayedRomsBySystem,importQueueURL,mainThreadContext,defaultDatabase,collections,storeURL,name,mipmap,texture,linearFiltering,path,wrapType,rom,file,archiveFileIndex,md5Hash,crcHash,fileName,shouldExit,limit,extractedFileURL,sourceURL,romObjectID,importer,exitStatus,exploreArchives,collectionID,completionHandler,checked,URL,error,systemIdentifiers,lineGradient,normalAttributes,splitVertically,image,clickAttributes,text,hoverAttributes,isInHover,loadingIndicator,currentImageIndex,currentImage,libraryController,tableView,developer,headerIndices,games,blankSlate,name,systemShortName,released,systemIdentifier,fileIndex,fileURLString,images,gameDescription,md5,added,website,currentDownload,systemGroup,URLs,target,doubleAction,localDelegate,superDelegate,borderWindow,dragging,mainContentView,contentBackgroundColor,stringValue,otherButtonTitle,defaultButton,boxView,height,alternateButtonTitle,headlineTextView,target,otherInputField,width,otherInputLabelText,inputField,messageTextView,suppressionLabelText,title,result,inputLimit,showsProgressbar,progressbar,defaultButtonTitle,progress,callback,callbackHandler,otherButton,messageText,headlineText,suppressionButton,otherStringValue,suppressionUDKey,inputLabelText,otherInputLabelView,suppressOnDefaultReturnOnly,alternateButton,showsSuppressionButton,showsOtherInputField,showsInputField,inputLabelView,window,hudWindow,draggingPoint,blocks,string,alignment,borderColor,font,delegate,cellClass,draggingOperation,groupThemeKey,proposedImage,automaticallyMinimizeRowMargin,lastWindowActive,lastImageSize,selectorImage,backgroundLayer,subtextLayer,textLayer,selectionLayer,foregroundLayer,type,lastWindowActive,lastImageSize,selectorImage,backgroundLayer,subtextLayer,textLayer,selectionLayer,foregroundLayer,ratingTracking,trackingCell,groupSubtitleAttributes,editingIndex,fieldEditor,groupBackgroundImage,lastPointInView,draggingIndex,groupTitleAttributes,draggingSession,indicationLayer,downloadButtonState,lastWindowActive,missingArtworkLayer,lastImageSize,ratingLayer,selectorImage,backgroundLayer,downloadLayer,textLayer,selectionLayer,proposedImageLayer,foregroundLayer,bounds,scaleFactor,aspectSize,disableNotifications,state,seconds,textureToRender,texture,notificationStepBackward,lastNotificationTime,type,supportsCheats,supportsDisplayModeChange,integralScalingDelegate,supportsFileInsertion,controlsWindow,gameView,systemIdentifier,document,supportsMultipleDiscs,supportsSaveStates,defaultScreenSize,discCount,coreIdentifier,displayModes,compiled,filePath,shaderName,shaderContext,compiled,filters,filterName,delegate,backgroundColor,syphonTitle,syphonServer,surfaceSize,presentationFramebuffer,ioSurface,gameCore,downloadProgress,sharedHelper,downloadVersion,updating,downloadProgress,downloadSession,database,updating,romFileURL,corePlugin,systemPlugin,systemIdentifier,rom,gameWindowController,volume,coreIdentifier,handleEvents,handleKeyboardEvents,emulationPaused,gameViewController,viewController,gameViewController,gameCoreHelper,ROMCRC32,displayModeInfo,ROMMD5,systemPlugin,ROMPath,plugin,gameCoreOwner,systemRegion,ROMHeader,ROMSerial,cheatsLoaded,controlsView,openMenus,fullScreenButton,lastMouseMovement,filterPlugins,fadeTimer,slider,cheats,pauseButton,eventMonitor,gameViewController,selectedViewTag,currentSearchTerm,gamesController,listViewSelectionChangeDate,volume,canShow,gameWindow,gameViewController,event,nextState,label,delay,fromState,fragmentPath,vertexPath,volume,outputDeviceID,notificationRenderer,cachedBoundsOnWindow,cachedBounds,cachedFrameSize,persistentKey,stream,errorHandler,itemDoneHandler,progressHandler,streamFlags,callbackBlock,delay,path,progress,downloadSession,destinationURL,url,error,waitSemaphore,progress,destinationURL,error,coverAspectRatio,name,icon,plugin,mutableGames,sharedDBScreenshotsMedia,sharedDBSavedGamesMedia,URL,screenshotURL,isSpecialState,systemIdentifier,displayName,valid,URL,location,dataFileURL,libraryDatabase,entityName,permanentID,permanentIDURI,localImageAvailable,sourceURL,UUID,imageURL,image,localFilesAvailable,saveStateCount,sourceURL,crcHashIfAvailable,tosec,mutableSaveStates,md5Hash,md5HashIfAvailable,URL,filesAvailable,crcHash,saveStateCount,defaultROM,playCount,mutableRoms,lastPlayed,displayName,mutableCollections,cleanDisplayName,playTime,mutableCredits,filesAvailable,mutableGenres,autosaveForLastPlayedRom,romDownload,mutableGames,games,name,sharedDBAllGamesCollection,widthInset,sharedUpdater,coreList,coreIdentifier,alert,coreDownload,requiredFiles,coreOptions,icon,gameCoreClass,bundleIdentifier,systemIdentifiers,controller,widthInset,progress,appcastItem,canBeInstalled,name,delegate,version,systemNames,appcast,bundleIdentifier,downloading,systemIdentifiers,hasUpdate,pinned,stringValue,state,action,target,collapsible,progress,downloading,fullPluginPath,downloadSession,buttonCell,fontFamily,action,target,state,title,highlightPoint,ringAlpha,action,selectedKey,image,keyPositions,target,ringPosition,imageMask,trackMouseActivity,modifierEventMonitor,themeImage,trackModifierActivity,backgroundThemeImage,trackWindowActivity,themeTextAttributes,selectedViewTag,libraryController,selectionIndexes,isSelected,gridView,selectedViewTag,listView,stateMask,themeImage,backgroundThemeImage,hovering,themed,themeTextAttributes,bindingsProvider,action,target,selectedKey,fragmentPreviousTextures,vertexPreviousTextureSizes,fragmentOriginalTexture,fragmentPreviousTextureSizes,vertexFrameRotation,fragmentVideoSize,vertexOriginalTextureVideoSize,frameCountMod,lutTextures,vertexProgram,fragmentOutputSize,vertexOriginalTextureCoords,fragmentFrameRotation,fragmentTextureSize,vertexVideoSize,fragmentOriginalTextureVideoSize,vertexOutputSize,yScaleType,xScaleType,vertexTextureSize,fragmentPassTextures,vertexFrameDirection,modelViewProj,fragmentPassTextureVideoSizes,fragmentPreviousTextureVideoSizes,fragmentProgram,scaler,fragmentOriginalTextureSize,vertexPassTextureVideoSizes,fragmentLUTTextures,linearFiltering,vertexPassTextureCoords,fragmentPassTextureSizes,fragmentFrameDirection,vertexFrameCount,vertexProfile,fragmentFrameCount,vertexPreviousTextureCoords,floatFramebuffer,vertexPassTextureSizes,fragmentProfile,vertexOriginalTextureSize,vertexPreviousTextureVideoSizes,widthInset,type,badgePosition,representedCollectionName,dragIndicationLayer,representedSystemPlugin,containerView,lastDragOperation,representedObject,containerView,delegate,longBuildVersion,buildVersion,spinnerLayer,innerShadowLayer,dropShadowLayer,trackMouseActivity,shouldFlipCoordinates,image,themeImage,backgroundThemeImage,trackWindowActivity,themeTextAttributes,backgroundColor,backgroundColorKey,stateMask,themed,hovering,sharedAudioDeviceManager,defaultInputDevice,deviceID,defaultOutputDevice,deviceName,audioDevices,numberOfOutputChannels,numberOfInputChannels,defaultSystemOutputDevice,fetchSortDescriptors,limit,textAttributes,scaleFactor,enableSubpixelAntialiasing,scaleFactor,perspectivePushed,grid,sourceAttributes,parent,verticalOffset,client,servers,textureSize,textureName,serverDescription,isValid,hasNewFrame,serverDescription,context,hasClients,name,lastUpdateCheckDate,hostBundle,automaticallyChecksForUpdates,httpHeaders,delegate,updateCheckInterval,updateInProgress,sendsSystemProfile,userAgentString,automaticallyDownloadsUpdates,decryptionPassword,sparkleBundle,feedURL,maximumSystemVersion,informationOnlyUpdate,contentLength,minimumSystemVersion,versionString,displayVersionString,osString,releaseNotesURL,fileURL,deltaUpdates,deltaUpdate,itemDescription,criticalUpdate,infoURL,dateString,macOsUpdate,DSASignature,title,propertiesDictionary,items,httpHeaders,userAgentString,request,textEncodingName,data,MIMEType,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,client,logger,client,serial,loggers,numberMessagesLogged,expectation,logs,logger,window,mj_insetB,mj_insetL,mj_offsetX,mj_insetR,mj_offsetY,mj_insetT,mj_contentW,mj_contentH,mj_inset,mj_origin,mj_h,mj_x,mj_y,mj_w,mj_size,webView,statusBarHidden,statusBarStyle,count,examples,methods,titles,vcClass,header,data,colors,window,method,s,logo,label,loading,s,label,loading,s,logo,label,loading,mj_footer,mj_header,languageCode,window,labelLeftInset,stateLabel,lastUpdatedTimeLabel,stateTitles,loadingView,window,labelLeftInset,stateLabel,activityIndicatorViewStyle,arrowView,loadingView,stateImages,stateDurations,stateTitles,window,gifView,gifView,activityIndicatorViewStyle,arrowView,loadingView,stateImages,stateDurations,stateTitles,window,activityIndicatorViewStyle,gifView,labelLeftInset,stateLabel,refreshingTitleHidden,stateImages,stateDurations,ignoredScrollViewContentInsetBottom,insetTDelta,ignoredScrollViewContentInsetTop,lastUpdatedTimeKey,lastUpdatedTime,pan,pullingPercent,automaticallyChangeAlpha,endRefreshingCompletionBlock,refreshing,state,refreshingAction,scrollViewOriginalInset,scrollView,refreshingTarget,refreshingBlock,beginRefreshingCompletionBlock,lastRefreshCount,lastBottomDelta,triggerAutomaticallyRefreshPercent,automaticallyRefresh,onlyRefreshPerDrag,oneNewPan,header,viewController,dataSource,layout,updater,frame,collectionView,adapter,window,workingRangeSize,viewController,dataSource,updater,collectionView,adapter,window,dataSource,adapter,window,collectionView,dataSource,adapter,window,collectionView,viewController,adapter,window,collectionView,mockDisplayDelegate,displayHandler,mockAdapterDataSource,object,mockAdapterDelegate,list,adapter,dataSource,collectionView,layout,dataSource,collectionView,mockCollectionView,collectionContext,viewController,dataSource,updater,collectionView,adapter,window,sd_imageTransition,sd_imageURL,sd_imageIndicator,sd_imageProgress,updateBlock,updater,dataSource,window,collectionView,sd_memoryCost,label,sd_isIncremental,sd_isAnimated,sd_imageLoopCount,sd_imageFormat,collectionView,sectionController,supportedElementKinds,size,dequeueFromNib,collectionContext,label,selected,supportedElementKinds,sectionController,collectionContext,objects,objects,objects,objects,label,delegate".Split(','));
                }

                string name = "";
                Random reum = new Random();
                for (int i = 0; i < 3; i++)
                {
                    int randomdata = Math.Max(1, reum.Next(wordLib.Count));//产生随机数
                    name += wordLib[randomdata];
                }

                return name;
            }
        }
    }
}